﻿using System;
using System.IO;
using System.Net;
using System.Xml;
using System.Xml.Serialization;
using System.Data;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Configuration;
using System.Reflection;
using System.Linq;
using System.Linq.Expressions;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.Text.RegularExpressions;
using System.Runtime;
using System.Runtime.InteropServices;

using PickGold.Nulls;
using PickGold.Handler;
using PickGold.Collections;

namespace PickGold.Util
{
	/// <summary>
	/// 将对象转成【Json】字符串，同时可以扩展或更改生成后的对象成员值
	/// </summary>
	[ComVisible(true)]
	[ClassInterface(ClassInterfaceType.AutoDispatch)]
	public class JsonBuilder : MarshalByRefObject, IJsonBuilder
	{
		#region inner class

		[Serializable]
		struct EmptyJson : IJsonBuilder
		{
			readonly static object _Graph = new object();

			bool IJsonBuilder.TryGetEP(string name, ref object value)
			{
				return false;
			}

			bool IJsonBuilder.TryGetEP(object key, string name, ref object value)
			{
				return false;
			}

			object IJsonBuilder.GetEP(string name)
			{
				return null;
			}

			object IJsonBuilder.SetEP(string name, object value)
			{
				throw new NotImplementedException();
			}

			object IJsonBuilder.GetEP(object key, string name)
			{
				return null;
			}

			object IJsonBuilder.SetEP(object key, string name, object value)
			{
				throw new NotImplementedException();
			}

			object IJsonBuilder.AppendEP(string name, object value)
			{
				throw new NotImplementedException();
			}

			object IJsonBuilder.AppendEP(object key, string name, object value)
			{
				throw new NotImplementedException();
			}

			string IJsonBuilder.ClassName
			{
				get
				{
					//throw new NotImplementedException();
					return string.Empty;
				}
				set
				{
					throw new NotImplementedException();
				}
			}

			string IJsonBuilder.Variable
			{
				get
				{
					//throw new NotImplementedException();
					return string.Empty;
				}
				set
				{
					throw new NotImplementedException();
				}
			}

			object IJsonBuilder.Graph
			{
				get
				{
					//throw new NotImplementedException();
					return EmptyJson._Graph;
				}
				set
				{
					throw new NotImplementedException();
				}
			}

			bool IJsonBuilder.IgnoreError
			{
				get
				{
					//throw new NotImplementedException();
					return true;
				}
				set
				{
					throw new NotImplementedException();
				}
			}

			void IJsonBuilder.RemoveEP(object key)
			{
				throw new NotImplementedException();
			}

			void IJsonBuilder.RemoveEP(object key, string name)
			{
				throw new NotImplementedException();
			}

			void IJsonBuilder.RemoveEP()
			{
				throw new NotImplementedException();
			}

			bool IJsonBuilder.HasEP()
			{
				return false;
			}

			bool IJsonBuilder.HasEP(string name)
			{
				return false;
			}

			bool IJsonBuilder.HasEP(object key, string name)
			{
				return false;
			}

			object IJsonBuilder.this[string name]
			{
				get
				{
					//throw new NotImplementedException();
					return null;
				}
				set
				{
					throw new NotImplementedException();
				}
			}

			object IJsonBuilder.this[object key, string name]
			{
				get
				{
					//throw new NotImplementedException();
					return null;
				}
				set
				{
					throw new NotImplementedException();
				}
			}

			public int Render(TextWriter output)
			{
				//throw new NotImplementedException();
				if (output == null)
					return 0;

				output.Write(JsonBuilder.NullString);
				return 1;
			}

			public int Render(TextWriter output, object graph, IDictionary<object, string> stack, string path, BindingFlags flags, string prefix)
			{
				//throw new NotImplementedException();
				if (output == null)
					return 0;

				if (graph == null)
					output.Write(JsonBuilder.NullString);
				output.Write(graph.ToString());
				return 1;
			}

			string IJsonBuilder.SetVariable(string parent, string variable)
			{
				throw new NotImplementedException();
			}

			string IJsonBuilder.SetVariable(string parent, string var0, string var1)
			{
				throw new NotImplementedException();
			}

			string IJsonBuilder.SetVariable(string parent, string var0, string var1, string var2)
			{
				throw new NotImplementedException();
			}

			public string ToString(BindingFlags bindingFlags)
			{
				//throw new NotImplementedException();
				return this.ToString();
			}

			public string ToString(bool staticMember)
			{
				//throw new NotImplementedException();
				return this.ToString();
			}

			public override string ToString()
			{
				//throw new NotImplementedException();
				return NullString;
			}
		}

		class JsonExpression
		{
			public ParameterExpression Graph;
			public ParameterExpression Json;//json
			public ParameterExpression Stack;
			public ParameterExpression Path;
			public ParameterExpression Writer;
			public ParameterExpression Flags;
			public ParameterExpression Writed;

			public BlockExpression Block;
			public LambdaExpression Lambda;
			public LabelTarget Label;

			public Delegate Handler;

			private Expression GetTestExpression(string p, ParameterExpression o, ParameterExpression d)
			{
				return this.GetTestExpression(Expression.Constant(p), o, d);
			}
			private Expression GetTestExpression(ConstantExpression p, ParameterExpression o, ParameterExpression d)
			{
				if (o == null)
					o = this.Graph;

				var e = this.GetTestExpression();
				var eb = e.Body as BinaryExpression;

				var el = eb.Left as BinaryExpression;
				var er = eb.Right as MethodCallExpression;
				var mm = el.Right as BinaryExpression;
				var ml = mm.Left as MethodCallExpression;
				var mr = mm.Right as ConstantExpression;
				var ll = el.Left as MethodCallExpression;
				var rr = er.Object as MethodCallExpression;

				var ec = Expression.Call(d, ml.Method, o);
				eb = Expression.NotEqual(ec, mr);
				eb = Expression.AndAlso(Expression.Call(d, ll.Method, o), eb);
				ec = Expression.Call(d, rr.Method, o);
				ec = Expression.Call(ec, er.Method, p);
				eb = Expression.AndAlso(eb, ec);
				return eb;
			}

			private Expression<Func<IDictionary<object, IDictionary<string, object>>, object, bool>> GetTestExpression()
			{
				//return (d, o, k) => d.ContainsKey(o) && d[o] != null && d[o].ContainsKey(k);
				return (d, o) => d.ContainsKey(o) && d[o] != null && d[o].ContainsKey(string.Empty);
			}

			private Expression GetValueExpression(string p, ParameterExpression o, ParameterExpression d)
			{
				return this.GetValueExpression(Expression.Constant(p), o, d);
			}
			private Expression GetValueExpression(ConstantExpression p, ParameterExpression o, ParameterExpression d)
			{
				if (o == null)
					o = this.Graph;

				var e = this.GetValueExpression();
				var eb = e.Body as MethodCallExpression;
				var rr = eb.Object as MethodCallExpression;

				rr = Expression.Call(d, rr.Method, o);
				eb = Expression.Call(rr, eb.Method, p);
				return eb;
			}

			private Expression<Func<IDictionary<object, IDictionary<string, object>>, object, object>> GetValueExpression()
			{
				return (d, o) => d[o][string.Empty];
			}

			public MethodInfo GetMethod(Delegate h, params Type[] ts)
			{
				var m = h.Method;
				var ps = m.GetParameters();
				var pl = ps.Length;
				if (ts == null || ts.Length != pl)
					ts = new Type[pl];
				for (var i = 0; i < pl; i++)
				{
					if (ts[i] == null)
						ts[i] = ps[i].ParameterType;
				}
				m = typeof(TextWriter).GetMethod(m.Name, ts);
				if (m == null)
					ts[0] = typeof(object);
				m = typeof(TextWriter).GetMethod(h.Method.Name, ts);
				return m;
			}
		}

		#endregion

		/// <summary>
		/// 空对象字符串：{}
		/// </summary>
		public const string EmptyJsonString = "{}";
		/// <summary>
		/// 空数组字符串：[]
		/// </summary>
		public const string EmptyArrayString = "[]";
		/// <summary>
		/// 申明字符串：var
		/// </summary>
		public const string VarString = "var";
		/// <summary>
		/// 空字符串：null
		/// </summary>
		public const string NullString = "null";
		/// <summary>
		/// 真字符串：null
		/// </summary>
		public const string TrueString = "true";
		/// <summary>
		/// 假字符串：null
		/// </summary>
		public const string FalseString = "false";

		/// <summary>
		/// 空对象，将生成【null】字符串，，如果设置扩展的对象是【Empty】则表示全局扩展
		/// </summary>
		public readonly static IJsonBuilder Empty = new EmptyJson();

		/// <summary>
		/// 默认缺省主体对象
		/// </summary>
		public readonly static object Any = new object();

		private readonly static IDictionary _MemberExcludeCache = Hashtable.Synchronized(new Hashtable());// new Dictionary<MemberInfo, object>();

		private object _Graph;
		private IDictionary<object, IDictionary<string, object>> _EP;

		/// <summary>
		/// 构造一Json实例
		/// </summary>
		public JsonBuilder()
		{
			this._Graph = null;
			this._EP = null;
		}

		/// <summary>
		/// 构造一Json实例
		/// </summary>
		/// <param name="graph">要转换的对象</param>
		public JsonBuilder(object graph)
		{
			this.Graph = graph;
			this._EP = null;
		}

		private JsonBuilder(object graph, string className)
		{
			this.ClassName = className;
			this.Graph = graph;
			this._EP = null;
		}

		/// <summary>
		/// 设置或获取扩展属性
		/// </summary>
		/// <param name="name">要获取或设置的属性名称</param>
		/// <returns>属性值</returns>
		public object this[string name]
		{
			set
			{
				if (this._Graph != null)
					this.SetEP(this._Graph, name, value);
			}
			get
			{
				return this.GetEP(this._Graph, name);
			}
		}
		/// <summary>
		/// 设置或获取扩展属性
		/// </summary>
		/// <param name="key">要获取或设置属性的对象，如果是【Empty】则表示全局扩展</param>
		/// <param name="name">要获取或设置的属性名称</param>
		/// <returns>属性值</returns>
		public object this[object key, string name]
		{
			set
			{
				this.SetEP(key, name, value);
			}
			get
			{
				return this.GetEP(key, name);
			}
		}

		/// <summary>
		/// 要转换的对象
		/// </summary>
		public object Graph
		{
			set
			{
				this._Graph = value;
			}
			get
			{
				return this._Graph;
			}
		}
		/// <summary>
		/// 要转换的对象
		/// </summary>
		public object Data
		{
			set
			{
				this._Graph = value;
			}
			get
			{
				return this._Graph;
			}
		}
		/// <summary>
		/// 要转换的对象
		/// </summary>
		public object Value
		{
			set
			{
				this._Graph = value;
			}
			get
			{
				return this._Graph;
			}
		}
		/// <summary>
		/// 要转换的对象
		/// </summary>
		public object Source
		{
			set
			{
				this._Graph = value;
			}
			get
			{
				return this._Graph;
			}
		}
		/// <summary>
		/// 要转换的对象
		/// </summary>
		public object Content
		{
			set
			{
				this._Graph = value;
			}
			get
			{
				return this._Graph;
			}
		}

		/// <summary>
		/// 类型名称字符串。
		/// </summary>
		public string ClassName { set; get; }

		/// <summary>
		/// 变量名。
		/// </summary>
		public string Variable { set; get; }

		/// <summary>
		/// 忽略错误。
		/// </summary>
		public bool IgnoreError { set; get; }

		/// <summary>
		/// 添加扩展
		/// </summary>
		/// <param name="name">扩展的成员名称，如果为空(Empty)字符串表示排除扩展列表，带星号(*)则表示排除列表</param>
		/// <param name="value">扩展的成员值</param>
		public object AppendEP(string name, object value)
		{
			if (this._Graph == null)
				return null;

			return this.SetEP(this._Graph, name, value);
		}

		/// <summary>
		/// 添加扩展
		/// </summary>
		/// <param name="key">扩展的对象，如果是【Empty】则表示全局扩展</param>
		/// <param name="name">扩展的成员名称，如果为空(Empty)字符串表示排除扩展列表，带星号(*)则表示排除列表</param>
		/// <param name="value">扩展的成员值</param>
		public object AppendEP(object key, string name, object value)
		{
			return this.SetEP(key, name, value);
		}

		/// <summary>
		/// 尝试获取扩展属性
		/// </summary>
		/// <param name="name">要尝试获取的属性名称</param>
		/// <param name="value">要尝试获取的属性值，带星号(*)则表示排除列表</param>
		/// <returns>是否获取成功</returns>
		public bool TryGetEP(string name, ref object value)
		{
			return TryGetEP(this._EP, this._Graph, name, ref value);
		}

		/// <summary>
		/// 尝试获取扩展属性
		/// </summary>
		/// <param name="key">要尝试获取属性的对象，如果是【Empty】则表示全局扩展</param>
		/// <param name="name">要尝试获取的属性名称，带星号(*)则表示排除列表</param>
		/// <param name="value">要尝试获取的属性值</param>
		/// <returns>是否获取成功</returns>
		public bool TryGetEP(object key, string name, ref object value)
		{
			return TryGetEP(this._EP, key, name, ref value);
		}

		/// <summary>
		/// 获取扩展属性
		/// </summary>
		/// <param name="name">要获取的属性名称，带星号(*)则表示排除列表</param>
		/// <returns>属性值</returns>
		public object GetEP(string name)
		{
			var v = Reflector<object>.DefaultValue;
			if (TryGetEP(this._EP, this._Graph, name, ref v))
				return v;

			return null;
		}

		/// <summary>
		/// 设置扩展属性
		/// </summary>
		/// <param name="name">要设置的属性名称</param>
		/// <param name="value">要设置的属性值，如果为空(Empty)字符串表示排除扩展列表，带星号(*)则表示排除列表</param>
		/// <returns>属性值</returns>
		public object SetEP(string name, object value)
		{
			if (this._Graph == null)
				return null;

			return this.SetEP(this._Graph, name, value);
		}

		/// <summary>
		/// 获取扩展属性
		/// </summary>
		/// <param name="key">要获取属性的对象，如果是【Empty】则表示全局扩展，带星号(*)则表示排除列表</param>
		/// <param name="name">要获取的属性名称</param>
		/// <returns>属性值</returns>
		public object GetEP(object key, string name)
		{
			var v = Reflector<object>.DefaultValue;
			if (TryGetEP(this._EP, key, name, ref v))
				return v;

			return null;
		}

		/// <summary>
		/// 设置扩展属性
		/// </summary>
		/// <param name="key">要设置属性的对象，如果是【Empty】则表示全局扩展</param>
		/// <param name="name">要设置的属性名称，如果为空(Empty)字符串表示排除扩展列表，带星号(*)则表示排除列表</param>
		/// <param name="value">要设置的属性值</param>
		/// <returns>属性值</returns>
		public object SetEP(object key, string name, object value)
		{
			if (key == null)
				key = JsonBuilder.Empty;
			if (this._EP == null)
				this._EP = new Dictionary<object, IDictionary<string, object>>();
			if (!this._EP.ContainsKey(key))
				this._EP[key] = new Dictionary<string, object>();
			this._EP[key][name] = value;
			return value;
		}

		/// <summary>
		/// 移除扩展
		/// </summary>
		public void RemoveEP()
		{
			this.RemoveEP(null, null);
		}
		/// <summary>
		/// 移除扩展
		/// </summary>
		/// <param name="key">扩展的对象，如果是【Empty】则表示全局扩展，带星号(*)则表示排除列表</param>
		public void RemoveEP(object key)
		{
			this.RemoveEP(key, null);
		}
		/// <summary>
		/// 移除扩展
		/// </summary>
		/// <param name="key">扩展的对象，如果是【Empty】则表示全局扩展，带星号(*)则表示排除列表</param>
		/// <param name="name">扩展的成员名称</param>
		public void RemoveEP(object key, string name)
		{
			if (this._EP == null)
				return;

			if (key == null)
				key = JsonBuilder.Empty;
			if (!this._EP.ContainsKey(key))
				return;

			if (name == null)
			{
				this._EP.Remove(key);
				return;
			}

			if (!this._EP[key].ContainsKey(name))
				return;

			this._EP[key].Remove(name);
		}

		/// <summary>
		/// 是否存在扩展
		/// </summary>
		/// <returns></returns>
		public bool HasEP()
		{
			if (this._EP == null)
				return false;

			return true;
		}

		/// <summary>
		/// 是否存在根对象扩展
		/// </summary>
		/// <param name="name">根对象扩展名，带星号(*)则表示排除列表</param>
		/// <returns></returns>
		public bool HasEP(string name)
		{
			var v = Reflector<object>.DefaultValue;
			return TryGetEP(this._EP, this._Graph, name, ref v);
		}

		/// <summary>
		/// 判断指定对象是否存在扩展或存在指定名称的扩展
		/// </summary>
		/// <param name="key">对象</param>
		/// <param name="name">指定对象的名称扩展，如果为空则表示指定对象是否存在任意扩展，带星号(*)则表示排除列表</param>
		/// <returns></returns>
		public bool HasEP(object key, string name)
		{
			var v = Reflector<object>.DefaultValue;
			return TryGetEP(this._EP, key, name, ref v);
		}

		/// <summary>
		/// 序列化成Json字符串
		/// </summary>
		/// <returns>用Json表示对象的字符串</returns>
		public virtual int Render(TextWriter output)
		{
			var json = this._Graph as JsonGraph;
			if (json != null)
				return json.Render(output);

			return JsonBuilder.Render(null, this, this._Graph, null, null, BindingFlags.Public | BindingFlags.Instance, output);
		}

		/// <summary>
		/// 输入指定对象的Json字符流
		/// </summary>
		/// <param name="output">Json书写器</param>
		/// <param name="graph">要输出的对象</param>
		/// <param name="stack">防止序列化死递归的堆对象</param>
		/// <param name="path">防止序列化死递归的引用路径</param>
		/// <param name="flags">指示序列化成员的标志</param>
		/// <param name="prefix">前缀字符串</param>
		/// <returns>是否已输出，为零表示没有任何输出，需要生成器继续处理。</returns>
		public virtual int Render(TextWriter output, object graph, IDictionary<object, string> stack, string path, BindingFlags flags, string prefix)
		{
			return 0;
		}

		/// <summary>
		/// 序列化成Json字符串
		/// </summary>
		/// <param name="input">前缀字符串</param>
		/// <param name="json">存有扩展对象Json对象</param>
		/// <param name="graph">要序列化的对象</param>
		/// <param name="stack">防止序列化死递归的堆对象</param>
		/// <param name="path">防止序列化死递归的引用路径</param>
		/// <param name="flags">指示序列化成员的标志</param>
		/// <param name="writer">输入缓存，如果存在，则内容输出到此缓存，并返回空；否则返回输出内容。</param>
		/// <returns>用Json表示对象的字符串，如果 output 不为空，则返回空。</returns>
		internal static int Render(string input, JsonBuilder json, object graph, IDictionary<object, string> stack, string path, BindingFlags flags, TextWriter writer)
		{
			if (graph == json && json != null)
				graph = json._Graph;
			var tw = writer;
			if (tw == null)
				tw = new StringWriter();
			if (!string.IsNullOrEmpty(input))
			{
				tw.Write(input);
				input = null;
			}
			if (stack == null)
			{
				input = "$" + (uint)json.GetHashCode();
				stack = new Dictionary<object, string>();
				tw.Write("(function ({0}{0}) {{ var {0} = ", input);
				if (string.IsNullOrEmpty(json.Variable))
					input = string.Format("; return {0}; }})({1})", input, NullString);
				else
					input = string.Format("; if(typeof({0}) == typeof(arguments.callee)) {0}({1}); else {0} = {1}; return {0}; }})(0)", json.Variable, input);//}})({0})"
			}
			var type = graph == null ? null : graph.GetType();
			var length = JsonBuilder.RenderPrimitive(graph, type, stack, path, tw, 0);//StringBuilder,TextReader,TextWriter,String,System value type object//输出值数据（可能）。
			if (length > 0)
				return RenderRecursion(json, stack, null, input, tw, length);//输出递归引用数据（仅递归赋值及结束代码）。

			if (stack.ContainsKey(graph))//StackOverflowException
			{
				length += RenderRecursion(json, stack, path, stack[graph], writer, length);//输出递归引用数据。
				return RenderRecursion(json, stack, null, input, tw, length);//输出递归引用数据（仅递归赋值及结束代码）。
			}

			var ms = new List<string>();
			stack.Add(graph, path);//添加到递归引用字典。
			length = json.Render(tw, graph, stack, path, flags, json.HasEP(graph, null) ? ", \"Value\": " : null);//特殊对象序列化处理
			if (length > 0)
			{
				length += JsonBuilder.RenderEP(json, graph, ms, stack, path, flags, tw, length);//输出扩展
				return RenderRecursion(json, stack, null, input, tw, length);//输出递归引用数据（仅递归赋值及结束代码）。
			}

			#region Object For(graph is): DataSet,DataTable,DataView,DataRow,DataRowView,IDataReader,XmlNode,IDictionary,NameObjectCollectionBase,IEnumerable

			var dataSet = graph as DataSet;
			if (dataSet != null)
			{
				length += JsonBuilder.RenderEP(json, graph, ms, stack, path, flags, tw, length);//输出扩展
				length += RenderDataSet(json, dataSet, stack, path, flags, tw, length);
				return RenderRecursion(json, stack, null, input, tw, length);//输出递归引用数据（仅递归赋值及结束代码）。
			}

			var dataTable = graph as DataTable;
			if (dataTable != null)
			{
				length += JsonBuilder.RenderEP(json, graph, ms, stack, path, flags, tw, length);//输出扩展
				length += RenderDataTable(json, dataTable, stack, path, flags, tw, length);
				return RenderRecursion(json, stack, null, input, tw, length);//输出递归引用数据（仅递归赋值及结束代码）。
			}

			var dataView = graph as DataView;
			if (dataView != null)
			{
				length += JsonBuilder.RenderEP(json, graph, ms, stack, path, flags, tw, length);//输出扩展
				length += RenderDataView(json, dataView, stack, path, flags, tw, length);
				return RenderRecursion(json, stack, null, input, tw, length);//输出递归引用数据（仅递归赋值及结束代码）。
			}

			var dataRow = graph as DataRow;
			if (dataRow != null)
			{
				length += JsonBuilder.RenderEP(json, graph, ms, stack, path, flags, tw, length);//输出扩展
				length += RenderDataRow(json, dataRow, stack, path, flags, tw, length);
				return RenderRecursion(json, stack, null, input, tw, length);//输出递归引用数据（仅递归赋值及结束代码）。;
			}

			var dataRowView = graph as DataRowView;
			if (dataRowView != null)
			{
				length += JsonBuilder.RenderEP(json, graph, ms, stack, path, flags, tw, length);//输出扩展
				length += RenderDataRowView(json, dataRowView, stack, path, flags, tw, length);
				return RenderRecursion(json, stack, null, input, tw, length);//输出递归引用数据（仅递归赋值及结束代码）。
			}

			var dataReader = graph as IDataReader;
			if (dataReader != null)
			{
				length += JsonBuilder.RenderEP(json, graph, ms, stack, path, flags, tw, length);//输出扩展
				length += RenderDataReader(json, dataReader, stack, path, flags, tw, length);
				return RenderRecursion(json, stack, null, input, tw, length);//输出递归引用数据（仅递归赋值及结束代码）。
			}

			var xml = graph as XmlNode;
			if (xml != null)
			{
				length += JsonBuilder.RenderEP(json, graph, ms, stack, path, flags, tw, length);//输出扩展
				length += RenderXmlNode(json, xml, stack, path, flags, tw, length);
				return RenderRecursion(json, stack, null, input, tw, length);//输出递归引用数据（仅递归赋值及结束代码）。
			}

			var dictionary = graph as IDictionary;
			if (dictionary != null)
			{
				length += JsonBuilder.RenderEP(json, graph, ms, stack, path, flags, tw, length);//输出扩展
				length += RenderDictionary(json, dictionary, stack, path, flags, tw, length);
				return RenderRecursion(json, stack, null, input, tw, length);//输出递归引用数据（仅递归赋值及结束代码）。
			}

			var nameValues = graph as NameObjectCollectionBase;
			if (nameValues != null)
			{
				length += JsonBuilder.RenderEP(json, graph, ms, stack, path, flags, tw, length);//输出扩展
				length += RenderNameObjectCollection(json, nameValues, stack, path, flags, tw, length);
				return RenderRecursion(json, stack, null, input, tw, length);//输出递归引用数据（仅递归赋值及结束代码）。
			}

			var enumerable = graph as IEnumerable;
			if (enumerable != null)
			{
				length += JsonBuilder.RenderEP(json, graph, ms, stack, path, flags, tw, length);//输出扩展
				length += RenderEnumerable(json, enumerable, stack, path, flags, tw, length);
				return RenderRecursion(json, stack, null, input, tw, length);//输出递归引用数据（仅递归赋值及结束代码）。
			}

			#endregion

			#region any other object(render fields and properties)

			if (typeof(object) == type)
			{
				length += JsonBuilder.RenderEP(json, graph, ms, stack, path, flags, tw, length);//输出扩展
				if (length == 0)
					writer.Write("{ }");
				else
					writer.Write(" }");
				return RenderRecursion(json, stack, null, input, tw, length);//输出递归引用数据（仅递归赋值及结束代码）。
			}

			var js = graph as IJsonSerializable;
			if (length == 0)
			{
				tw.Write("{ \"$:type\": \"");
				tw.Write(StringUtil.JsEncode(json.ClassName ?? type.FullName));
				tw.Write("\"");
				length++;
			}
			if (js != null)
			{
				length += RenderSerializable(json, graph, stack, path, flags, tw, length, js);
			}
			else
			{
				if (Utility.StaticCache.FormJsonTypeRender != null && Utility.StaticCache.FormJsonTypeRender.ContainsKey(type))
				{
					var h = Utility.StaticCache.FormJsonTypeRender[type];
					if (h != null)
					{
						try
						{
							length += (int)h.DynamicInvoke(json, graph, ms, stack, path, flags, tw, length);
							tw.Write(", \"$:h\": 1");
							length += JsonBuilder.RenderEP(json, graph, ms, stack, path, flags, tw, length);//输出扩展
							graph = null;
						}
						catch (Exception x)
						{
							tw.Write(", \"$:" + StringUtil.JsEncode(h.Method.Name) + "\": \"" + StringUtil.JsEncode(x.ToString()) + "\"");
							length++;
						}
					}
				}

				if (graph != null)
				{
					var ps = type.GetProperties(flags);
					if (ps != null)
					{
						foreach (var m in ps)
							ms.Add(m.Name);
						length += RenderProperties(json, graph, stack, path, flags, tw, length, ps);
					}
					var fs = type.GetFields(flags);
					if (fs != null)
					{
						foreach (var m in ps)
							ms.Add(m.Name);
						length += RenderFields(json, graph, stack, path, flags, tw, length, fs);
					}
					try
					{
						LambdaMember(type, ps, fs, json, ms, tw);
					}
					catch (Exception x)
					{
						tw.Write(", \"$:Lambda::Compile\": \"" + StringUtil.JsEncode(x.ToString()) + "\"");
						if (Utility.StaticCache.FormJsonTypeRender == null)
							Utility.StaticCache.FormJsonTypeRender = new Dictionary<Type, Delegate>();
						Utility.StaticCache.FormJsonTypeRender[type] = null;
					}
					length += JsonBuilder.RenderEP(json, graph, ms, stack, path, flags, tw, length);//输出扩展
				}
			}
			tw.Write(" }");
			//sb.Write("\"$\": " + Json.JsEncode(graph.ToString()) + " }");
			length++;

			#endregion

			return RenderRecursion(json, stack, null, input, tw, length);//输出递归引用数据（仅递归赋值及结束代码）。
		}

		/// <summary>
		/// Stack Overflow Exception: throw new StackOverflowException();
		/// </summary>
		/// <param name="json"></param>
		/// <param name="stack"></param>
		/// <param name="path"></param>
		/// <param name="value"></param>
		/// <param name="writer"></param>
		/// <param name="writed"></param>
		/// <returns></returns>
		private static int RenderRecursion(IJsonBuilder json, IDictionary<object, string> stack, string path, string value, TextWriter writer, int writed)//输出递归引用数据。
		{
			/*
			function ($1)
			{
				if (!$1)
					return arguments.callee;

				if (!$1.length || $1.length < 3 || $1[0] != $1[1] || $1[1] != $1[2])
					$1 = [$1, $1, $12];																		//$12 = p_0, p_1, p_2, p_3, p_4 
				for (var $01 = 3; $01 < $1.length; $01++)
				{
					$1[1] = $1[0];
					$1[0] = $1[0][$1[$01]];
				}
				if (typeof($1[0]) == typeof(arguments.callee))
					$1[1][$1[$1.length - 1]] = $1[0]($1[2]);
				return $1[0];
			}
			*/
			const string STACK_OVERFLOW_FUNCTION = "function (${1}) {{ if (!${1}) return arguments.callee; if (!${1}.length || ${1}.length < 3 || ${1}[0] != ${1}[1] || ${1}[1] != ${1}[2]) ${1} = [ ${1}, ${1}, ${1}{2} ]; for (var $_{1} = 3; $_{1} < ${1}.length; $_{1}++) {{ ${1}[1] = ${1}[0]; ${1}[0] = ${1}[0][${1}[$_{1}]]; }} if (typeof(${1}[0]) == typeof(arguments.callee)) ${1}[1][${1}[${1}.length - 1]] = ${1}[0](${1}[2]); return ${1}[0]; }}";
			if (string.IsNullOrEmpty(path))//结束代码
			{
				if (value == null)
					return writed;

				path = null;
				foreach (var key in stack.Keys)//处理所有需要递归的值
				{
					if (key is int)
					{
						if (path == null)
						{
							path = "; var $_{0} = " + STACK_OVERFLOW_FUNCTION;
							writer.Write(path, (uint)json.GetHashCode(), (uint)stack.GetHashCode(), string.Empty);
						}
						writer.Write("; $_{0}([ ${0}, ${0}, ${0}{1} ])", (uint)json.GetHashCode(), stack[key]);
					}
				}
				writer.Write(value);
				return writed;
			}

			//throw new StackOverflowException();//StackOverflowException
			if (writer == null)//if (string.IsNullOrEmpty(value) || writer == null)
				throw new StackOverflowException();

			//if (value == null)
			//	value = string.Empty;
			//if (value == null)
			//    value = ((uint)string.Empty.GetHashCode()) + string.Empty;
			//else
			//    value = ((uint)value.GetHashCode()) + string.Empty;
			stack.Add(stack.Count, path);
			path = "(" + STACK_OVERFLOW_FUNCTION + ")({0})";//${0}
			if (writed == 0)
			{
				writer.Write(path, NullString/*(uint)json.GetHashCode()*/, (uint)(value ?? string.Empty).GetHashCode(), value);
				return 1;
			}

			writer.Write(", \"Value\": ");
			writer.Write(path, NullString/*(uint)json.GetHashCode()*/, (uint)(value ?? string.Empty).GetHashCode(), value);
			writer.Write(" }");
			return writed + 1;
		}

		/// <summary>
		/// Graph Extend Properties
		/// </summary>
		/// <param name="json"></param>
		/// <param name="graph"></param>
		/// <param name="exclude">排除的扩展，已处理过的扩展</param>
		/// <param name="stack"></param>
		/// <param name="path"></param>
		/// <param name="bindingFlags"></param>
		/// <param name="writer"></param>
		/// <param name="writed"></param>
		/// <returns></returns>
		private static int RenderEP(JsonBuilder json, object graph, IList<string> exclude, IDictionary<object, string> stack, string path, BindingFlags bindingFlags, TextWriter writer, int writed)//输出扩展
		{
			var write = 0;
			if (json == null || graph == null || graph is IJsonBuilder || graph is DBNull)
				return write;

			if (json._EP == null)
				return write;

			var ep = Reflector<string, object>.NullDictionaryI;
			var ea = Reflector<string, object>.NullDictionaryI;
			json._EP.TryGetValue(graph, out ep);
			json._EP.TryGetValue(JsonBuilder.Empty, out ea);
			if ((ep == null || ep.Count == 0) && (ea == null || ea.Count == 0))
				return write;

			if (ep != null)
			{
				foreach (var kvp in ep)
				{
					if (string.IsNullOrEmpty(kvp.Key))
						continue;

					var ex = exclude;
					foreach (var x in exclude)
					{
						if (x == kvp.Key)
						{
							ex = null;
							break;
						}
					}
					if (ex == null)
						continue;

					exclude.Add(kvp.Key);
					if (kvp.Value == null)
						continue;

					if (write == 0 && writed == 0)
					{
						writer.Write("{ \"$:type\": \"");
						writer.Write(StringUtil.JsEncode(json.ClassName ?? graph.GetType().FullName));
						writer.Write("\"");
						write++;
					}
					writer.Write(", ");
					JsonBuilder.Render("\"" + StringUtil.JsEncode(kvp.Key) + "\": ", json, kvp.Value, stack, path + ", \"" + StringUtil.JsEncode(kvp.Key) + "\"", bindingFlags, writer);
					write++;
				}
			}
			if (ea != null)
			{
				foreach (var kvp in ea)
				{
					if (string.IsNullOrEmpty(kvp.Key))
						continue;

					var ex = exclude;
					foreach (var x in exclude)
					{
						if (x == kvp.Key)
						{
							ex = null;
							break;
						}
					}
					if (ex == null)
						continue;

					exclude.Add(kvp.Key);
					if (kvp.Value == null)
						continue;

					if (write == 0 && writed == 0)
					{
						writer.Write("{ \"$:type\": \"");
						writer.Write(StringUtil.JsEncode(json.ClassName ?? graph.GetType().FullName));
						writer.Write("\"");
						write++;
					}
					writer.Write(", ");
					JsonBuilder.Render("\"" + StringUtil.JsEncode(kvp.Key) + "\": ", json, kvp.Value, stack, path + ", \"" + StringUtil.JsEncode(kvp.Key) + "\"", bindingFlags, writer);
					write++;
				}
			}
			//if (write > 0)
			//{
			//    writer.Write(", \"Value\": ");
			//    write++;
			//}
			return write;
		}

		/// <summary>
		/// For value type object, but struct.
		/// </summary>
		/// <param name="graph"></param>
		/// <param name="type">如果为空则强制输出内容，返回结果总为非零值。</param>
		/// <param name="stack"></param>
		/// <param name="path"></param>
		/// <param name="writer"></param>
		/// <param name="writed">已定入次数，如果非零则输出 【, Value:】 属性名前缀。</param>
		/// <returns>如果为非值类型前【type】非空，则返回零</returns>
		private static int RenderPrimitive(object graph, Type type, IDictionary<object, string> stack, string path, TextWriter writer, int writed)//输出值数据。
		{
			const string PROPERTY_NAME_VALUE = ", \"Value\": ";
			//if (!stack.ContainsKey(graph))
			//	stack.Add(graph, path);
			//if (graph is IBoxValue)
			//{
			//    var bv = (IBoxValue)graph;
			//    type = bv.GetType();
			//    graph = bv.GetValue();
			//}
			if (graph == null || graph is IJsonBuilder || graph is DBNull)
			{
				if (writed > 0)
					writer.Write(PROPERTY_NAME_VALUE);
				var json = graph as JsonGraph;
				if (json != null && json.Graph != null)
					json.Render(writer);
				else
					writer.Write(NullString);
				return 1;
			}

			if (graph is bool)
			{
				if (writed > 0)
					writer.Write(PROPERTY_NAME_VALUE);
				if (graph.Equals(true))
					writer.Write(TrueString);
				else
					writer.Write(FalseString);
				return 1;
			}

			if (graph is DateTime)
			{
				if (writed > 0)
					writer.Write(PROPERTY_NAME_VALUE);
				var dateTime = (DateTime)graph;
				//var tt = "new Date({0}, {1}, {2}, {3}, {4}, {5}, {6})";
				//return string.Format(tt, dateTime.Year, dateTime.Month - 1, dateTime.Day, dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond);
				if (Common.DefaultDateTimeKind == DateTimeKind.Local && dateTime.Kind != DateTimeKind.Utc)
					dateTime = dateTime.ToUniversalTime();
				writer.Write("new Date({0})", (dateTime.Ticks - Common.JsBaseTicks) / TimeSpan.TicksPerMillisecond);
				return 1;
			}

			if (type == null)//强制输出内容
			{
				if (writed > 0)
					writer.Write(PROPERTY_NAME_VALUE);
				writer.Write("\"");
				writer.Write(graph);
				writer.Write("\"");
				return 1;
			}

			if (graph is sbyte || graph is byte ||
				graph is short || graph is ushort ||
				graph is int || graph is uint ||
				graph is long || graph is ulong ||
				graph is float || graph is double || graph is decimal)
			{
				if (writed > 0)
					writer.Write(PROPERTY_NAME_VALUE);
				writer.Write("\"");
				writer.Write(graph);
				writer.Write("\"");
				return 1;
			}

			if (graph is char ||
				graph is string ||
				graph is Enum ||
				graph is IntPtr ||
				graph is Guid ||
				graph is Binary ||
				graph is TimeSpan ||
				graph is StringBuilder ||
				graph is TextWriter ||
				graph is IPAddress ||
				//graph is IXmlValue ||
				graph is MemberInfo ||
				graph is Delegate)
			{
				if (writed > 0)
					writer.Write(PROPERTY_NAME_VALUE);
				writer.Write("\"");
				writer.Write(StringUtil.JsEncode(graph + string.Empty));
				writer.Write("\"");
				return 1;
			}

			var bs = graph as byte[];
			if (bs != null)
			{
				if (writed > 0)
					writer.Write(PROPERTY_NAME_VALUE);
				writer.Write("\"");
				writer.Write(Convert.ToBase64String(bs));
				writer.Write("\"");
				return 1;
			}

			var tr = graph as TextReader;
			if (tr != null)
			{
				if (writed > 0)
					writer.Write(PROPERTY_NAME_VALUE);
				writer.Write("\"");
				writer.Write(StringUtil.JsEncode(tr.ReadLine()));
				writer.Write("\"");
				return 1;
			}

			return 0;
		}

		/// <summary>
		/// For value type object, but struct.
		/// </summary>
		/// <param name="graph"></param>
		/// <param name="type">如果为空则强制输出内容，返回结果总为非零值。</param>
		/// <param name="value"></param>
		/// <returns>如果为非值类型前【type】非空，则返回零</returns>
		private static Expression LambdaPrimitive(JsonExpression graph, string value)//输出值数据。
		{
			if (string.IsNullOrEmpty(value))
				return null;

			return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant(value));//writer.Write(graph);
		}
		/// <summary>
		/// For value type object, but struct.
		/// </summary>
		/// <param name="graph"></param>
		/// <param name="type">如果为空则强制输出内容，返回结果总为非零值。</param>
		/// <param name="value"></param>
		/// <returns>如果为非值类型前【type】非空，则返回零</returns>
		private static IEnumerable<Expression> LambdaPrimitive(JsonExpression graph, Type type, Expression value, string name, string prefix)//输出值数据。
		{
			if (graph == null || value == null)
			{
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant(prefix));
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant(NullString));
				yield return Expression.Increment(graph.Writed);//writed++
				yield break;
			}

			//if (!stack.ContainsKey(graph))
			//	stack.Add(graph, path);
			//var e = Expression.IfThen(Expression.GreaterThan(graph.Writed, Expression.Constant(0)), Expression.Call(graph.Writer, graph.WriterWrite, Expression.Constant(PROPERTY_NAME_VALUE)));//if (writed > 0)	writer.Write(PROPERTY_NAME_VALUE);
			if (type == null)//强制输出内容//值类型一定是字符串
			{
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant(prefix));
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write), type), value);//writer.Write(graph);
				yield return Expression.Increment(graph.Writed);//writed++
				yield break;
			}

			if (type == typeof(sbyte) || type == typeof(byte) ||
				type == typeof(short) || type == typeof(ushort) ||
				type == typeof(int) || type == typeof(uint) ||
				type == typeof(long) || type == typeof(ulong) ||
				type == typeof(float) || type == typeof(double) ||
				type == typeof(decimal))
			{
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant(prefix));
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant("\""));//writer.Write("\"");
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write), type), value);//writer.Write(graph);
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant("\""));//writer.Write("\"");
				yield return Expression.Increment(graph.Writed);//writed++
				yield break;
			}

			if (type == typeof(Enum) ||
				type == typeof(IntPtr) ||
				type == typeof(Guid) ||
				type == typeof(TimeSpan))
			{
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant(prefix));
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant("\""));//writer.Write("\"");
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write), type), Expression.Call(value, new Func<string>(type.ToString).Method.Name, null));//writer.Write(graph);
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant("\""));//writer.Write("\"");
				yield return Expression.Increment(graph.Writed);//writed++
				yield break;
			}

			if (type == typeof(DBNull))
			{
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant(prefix));
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant(NullString));
				yield return Expression.Increment(graph.Writed);//writed++
				yield break;
			}

			if (type == typeof(bool))
			{
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant(prefix));
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Condition(value, Expression.Constant(TrueString), Expression.Constant(FalseString)));
				yield return Expression.Increment(graph.Writed);//writed++
				yield break;
			}

			if (type == typeof(char))
			{
				var jem = new Func<string>(Reflector<char>.Value.ToString).Method;
				var jec = Expression.Call(value, jem);
				jem = new Func<object, string>(StringUtil.JsEncode).Method;
				jec = Expression.Call(null, jem, jec);
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant(prefix));
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant("\""));//writer.Write("\"");
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), jec);//writer.Write(JsonBuilder.JsEncode(graph.ToString));
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant("\""));//writer.Write("\"");
				yield return Expression.Increment(graph.Writed);//writed++
				yield break;
			}

			if (type == typeof(DateTime))
			{
				var jem = new Func<DateTime, string>(StringUtil.JsEncode).Method;
				var jec = Expression.Call(null, jem, value);
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant(prefix));
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), jec);//writer.Write(JsonBuilder.JsEncode(graph.ToString));
				yield break;
			}

			if (type == typeof(string))
			{
				var jem = new Func<string, string>(StringUtil.JsEncode).Method;
				var jec = Expression.Call(null, jem, value);
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant(prefix));
				yield return Expression.Block(
								Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant("\"")),//writer.Write("\"");
								Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), jec),
								Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant("\""))//writer.Write("\"");
							);
				yield return Expression.Increment(graph.Writed);//writed++
				yield break;
			}

			if (type.IsSubclassOf(typeof(byte[])))
			{
				var jem = typeof(TextReader).GetMethod(new Func<byte[], string>(Convert.ToBase64String).Method.Name);
				var jec = Expression.Call(value, jem);
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant(prefix));
				yield return Expression.Block(
						Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant("\"")),//writer.Write("\"");
						Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), jec),
						Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant("\""))//writer.Write("\"");
					);
				yield return Expression.Increment(graph.Writed);//writed++
				yield break;
			}

			if (type.IsSubclassOf(typeof(TextReader)))
			{
				var jem = typeof(TextReader).GetMethod(new Func<string>(NullTextReader.Value.ReadToEnd).Method.Name);
				var jec = Expression.Call(value, jem);
				jem = new Func<string, string>(StringUtil.JsEncode).Method;
				jec = Expression.Call(null, jem, jec);
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant(prefix));
				yield return Expression.Block(
						Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant("\"")),//writer.Write("\"");
						Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), jec),
						Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant("\""))//writer.Write("\"");
					);
				yield return Expression.Increment(graph.Writed);//writed++
				yield break;
			}

			if (type == typeof(StringBuilder) ||
				type.IsSubclassOf(typeof(TextWriter)) ||
				type == typeof(Binary) ||
				type == typeof(IPAddress) || type.IsSubclassOf(typeof(IPAddress)) ||
				//type == typeof(IXmlValue) || type.IsSubclassOf(typeof(IXmlValue)) ||
				type.IsSubclassOf(typeof(MemberInfo)) ||// type.IsSubclassOf(typeof(MemberInfo)) ||
				type.IsSubclassOf(typeof(Delegate)) ||// type.IsSubclassOf(typeof(Delegate)) ||
				type == typeof(Exception) || type.IsSubclassOf(typeof(Exception)))
			{
				var jem = new Func<object, string>(StringUtil.JsEncode).Method;
				var jec = Expression.Call(null, jem, value);
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant(prefix));
				yield return Expression.Block(
						Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant("\"")),//writer.Write("\"");
						Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), jec),
						Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant("\""))//writer.Write("\"");
					);
				yield return Expression.Increment(graph.Writed);//writed++
				yield break;
			}

			if (type.IsSubclassOf(typeof(IJsonBuilder)))
			{
				var rm = new Func<TextWriter, int>(((IJsonBuilder)new EmptyJson()).Render).Method;
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant(prefix));
				yield return Expression.AddAssign(graph.Writed, Expression.Call(value, rm, graph.Writer));
			}
			else
			{
				var rm = new Func<string, JsonBuilder, object, IDictionary<object, string>, string, BindingFlags, TextWriter, int>(JsonBuilder.Render).Method;
				yield return Expression.Call(graph.Writer, graph.GetMethod(new Action<string>(NullTextWriter.Value.Write)), Expression.Constant(prefix));
				yield return Expression.AddAssign(graph.Writed, Expression.Call(null,
																				rm,// JsonBuilder.Render
																				Expression.Constant(null, typeof(string)),
																				graph.Json,
																				Expression.Convert(value, typeof(object)),
																				graph.Stack,
																				Expression.Call(null, new Func<string, string, string>(string.Concat).Method,// path + ", \"" + JsonBuilder.JsEncode(m.Name) + "\""
																					Expression.Call(null, new Func<string, string, string>(string.Concat).Method,
																						Expression.Call(null, new Func<string, string, string>(string.Concat).Method, graph.Path, Expression.Constant(", \"")),
																							Expression.Constant(StringUtil.JsEncode(name))
																					), Expression.Constant("\"")
																				),// graph.Path,
																				graph.Flags,
																				graph.Writer));
			}
			yield break;
		}

		private static int LambdaMember(Type type, PropertyInfo[] propertities, FieldInfo[] fields, IJsonBuilder json, ICollection<string> exclude, TextWriter writer)
		{
			var em = typeof(IJsonBuilder).GetMethod(new TryRefHandler<bool, object, string, object>(json.TryGetEP).Method.Name, new Type[] { typeof(object), typeof(string), typeof(object).MakeByRefType(), });
			var rm = new Func<string, JsonBuilder, object, IDictionary<object, string>, string, BindingFlags, TextWriter, int>(JsonBuilder.Render).Method;
			var lm = typeof(ICollection<string>).GetMethod(new Action<string>(exclude.Add).Method.Name, new Type[] { typeof(string), });
			var eNs = new List<Expression>();
			var eHs = new List<Expression>();
			var eAs = new List<Expression>();
			var eEP = Expression.Parameter(typeof(IList<string>), "e");
			var eEv = Expression.Variable(typeof(object), "v");
			var eie = Expression.Variable(typeof(bool), "i");
			var et = Reflector<Expression>.DefaultValue;
			var el = Reflector<Expression>.DefaultValue;
			var er = Reflector<Expression>.DefaultValue;
			var graph = new JsonExpression();
			graph.Json = Expression.Parameter(typeof(JsonBuilder), "j");//IJsonBuilder
			graph.Graph = Expression.Parameter(type, "g");
			graph.Stack = Expression.Parameter(typeof(IDictionary<object, string>), "s");
			graph.Path = Expression.Parameter(typeof(string), "p");
			graph.Flags = Expression.Parameter(typeof(BindingFlags), "f");
			graph.Writer = Expression.Parameter(typeof(TextWriter), "w");
			graph.Writed = Expression.Parameter(typeof(int), "c");
			graph.Label = Expression.Label(typeof(int));
			foreach (var m in propertities)
			{
				if (m == null)
					continue;

				et = Expression.Call(eEP, lm, Expression.Constant(m.Name));
				eHs.Add(et);
				eNs.Add(et);
				et = Expression.Call(graph.Json, em, Expression.Convert(graph.Graph, typeof(object)), Expression.Constant(m.Name), eEv);
				er = Expression.Call(null, new Func<string, string, string>(string.Concat).Method,// path + ", \"" + JsonBuilder.JsEncode(m.Name) + "\""
							Expression.Call(null, new Func<string, string, string>(string.Concat).Method,
								Expression.Call(null, new Func<string, string, string>(string.Concat).Method, graph.Path, Expression.Constant(", \"")),
									Expression.Constant(StringUtil.JsEncode(m.Name))
							), Expression.Constant("\"")
						);
				el = Expression.Call(null, rm
					, Expression.Constant(null, typeof(string))//input
					, graph.Json//json
					, eEv//graph
					, graph.Stack//stack
					, er//path
					, graph.Flags//flags
					, graph.Writer//wirter
					//, graph.Writed//wirted
					);
				el = Expression.Block(LambdaPrimitive(graph, ", \"" + StringUtil.JsEncode(m.Name) + "\": "), el, Expression.Increment(graph.Writed));
				el = Expression.IfThen(Expression.NotEqual(eEv, Expression.Constant(null)), el);//if(v != null) render(json, v, stack, path, flags, wirter);
				if (JsonBuilder._MemberExcludeCache[m] != null)
				{
					er = null;
				}
				else
				{
					var t = typeof(Exception);
					var p = Expression.Variable(t, "x");
					var tNullable = Nullable.GetUnderlyingType(m.PropertyType);
					if (tNullable != null)
					{
						er = Expression.Convert(Expression.Property(graph.Graph, m), tNullable);
						try
						{
							er = Expression.IfThen(Expression.AndAlso(Expression.NotEqual(Expression.Property(graph.Graph, m), Expression.Constant(null)), Expression.NotEqual(er, Expression.Default(tNullable))),
								Expression.Block(LambdaPrimitive(graph, tNullable, er, m.Name, ", \"" + StringUtil.JsEncode(m.Name) + "\": ")));
						}
						catch (InvalidOperationException)
						{
							er = Expression.IfThen(Expression.AndAlso(Expression.NotEqual(Expression.Property(graph.Graph, m), Expression.Constant(null)), Expression.Not(Expression.Call(null, new Func<object, object, bool>(object.Equals).Method, Expression.Convert(er, typeof(object)), Expression.Convert(Expression.Default(tNullable), typeof(object))))),
								Expression.Block(LambdaPrimitive(graph, tNullable, er, m.Name, ", \"" + StringUtil.JsEncode(m.Name) + "\": ")));
						}
					}
					else
					{
						er = Expression.Property(graph.Graph, m);
						try
						{
							er = Expression.IfThen(Expression.NotEqual(er, Expression.Default(m.PropertyType)),//没有为 PropertyType 定义二进制运算符 NotEqual
								Expression.Block(LambdaPrimitive(graph, m.PropertyType, er, m.Name, ", \"" + StringUtil.JsEncode(m.Name) + "\": ")));
						}
						catch (InvalidOperationException)
						{
							er = Expression.IfThen(Expression.Not(Expression.Call(null, new Func<object, object, bool>(object.Equals).Method, Expression.Convert(er, typeof(object)), Expression.Convert(Expression.Default(m.PropertyType), typeof(object)))),//没有为 PropertyType 定义二进制运算符 NotEqual
								Expression.Block(LambdaPrimitive(graph, m.PropertyType, er, m.Name, ", \"" + StringUtil.JsEncode(m.Name) + "\": ")));
						}
					}
					er = Expression.IfThenElse(eie, Expression.TryCatch(er, Expression.Catch(p, Expression.IfThen(eie, Expression.Block(LambdaPrimitive(graph, t, p, m.Name, ", \"" + StringUtil.JsEncode(m.Name) + "\": "))))), er);
				}
				if (er == null)
				{
					eHs.Add(Expression.IfThen(et, el));
					continue;
				}

				eHs.Add(Expression.IfThenElse(et, el, er));
				eNs.Add(er);
			}
			foreach (var m in fields)
			{
				if (m == null)
					continue;

				et = Expression.Call(eEP, lm, Expression.Constant(m.Name));
				eHs.Add(et);
				eNs.Add(et);
				et = Expression.Call(graph.Json, em, Expression.Convert(graph.Graph, typeof(object)), Expression.Constant(m.Name), eEv);
				er = Expression.Call(null, new Func<string, string, string>(string.Concat).Method,// path + ", \"" + JsonBuilder.JsEncode(m.Name) + "\""
							Expression.Call(null, new Func<string, string, string>(string.Concat).Method,
								Expression.Call(null, new Func<string, string, string>(string.Concat).Method, graph.Path, Expression.Constant(", \"")),
									Expression.Constant(StringUtil.JsEncode(m.Name))
							), Expression.Constant("\"")
						);
				el = Expression.Call(null, rm
					, Expression.Constant(null, typeof(string))//input
					, graph.Json//json
					, eEv//graph
					, graph.Stack//stack
					, er//path
					, graph.Flags//flags
					, graph.Writer//wirter
					//, graph.Writed//wirted
					);
				el = Expression.Block(LambdaPrimitive(graph, ", \"" + StringUtil.JsEncode(m.Name) + "\": "), el, Expression.Increment(graph.Writed));
				el = Expression.IfThen(Expression.NotEqual(eEv, Expression.Constant(null)), el);//if(v != null) render(json, v, stack, path, flags, wirter);
				if (JsonBuilder._MemberExcludeCache[m] != null)
				{
					er = null;
				}
				else
				{
					var tNullable = Nullable.GetUnderlyingType(m.FieldType);
					if (tNullable != null)
					{
						er = Expression.Convert(Expression.Field(graph.Graph, m), tNullable);
						try
						{
							er = Expression.IfThen(Expression.AndAlso(Expression.NotEqual(Expression.Field(graph.Graph, m), Expression.Constant(null)), Expression.NotEqual(er, Expression.Default(tNullable))),
								Expression.Block(LambdaPrimitive(graph, tNullable, er, m.Name, ", \"" + StringUtil.JsEncode(m.Name) + "\": ")));
						}
						catch (InvalidOperationException)
						{
							er = Expression.IfThen(Expression.AndAlso(Expression.NotEqual(Expression.Field(graph.Graph, m), Expression.Constant(null)), Expression.Not(Expression.Call(null, new Func<object, object, bool>(object.Equals).Method, Expression.Convert(er, typeof(object)), Expression.Convert(Expression.Default(tNullable), typeof(object))))),
								Expression.Block(LambdaPrimitive(graph, tNullable, er, m.Name, ", \"" + StringUtil.JsEncode(m.Name) + "\": ")));
						}
					}
					else
					{
						er = Expression.Field(graph.Graph, m);
						try
						{
							er = Expression.IfThen(Expression.NotEqual(er, Expression.Default(m.FieldType)),
								Expression.Block(LambdaPrimitive(graph, m.FieldType, er, m.Name, ", \"" + StringUtil.JsEncode(m.Name) + "\": ")));
						}
						catch (InvalidOperationException)
						{
							er = Expression.IfThen(Expression.Not(Expression.Call(null, new Func<object, object, bool>(object.Equals).Method, Expression.Convert(er, typeof(object)), Expression.Convert(Expression.Default(m.FieldType), typeof(object)))),
								Expression.Block(LambdaPrimitive(graph, m.FieldType, er, m.Name, ", \"" + StringUtil.JsEncode(m.Name) + "\": ")));
						}
					}
				}
				if (er == null)
				{
					eHs.Add(Expression.IfThen(et, el));
					continue;
				}

				eHs.Add(Expression.IfThenElse(et, el, er));
				eNs.Add(er);
			}
			eAs.Add(Expression.IfThen(Expression.Equal(graph.Json, Expression.Constant(null)), Expression.Throw(Expression.New(typeof(ArgumentException).GetConstructor(new Type[] { typeof(string), }), Expression.Constant(graph.Json.Name)))));
			eAs.Add(Expression.IfThen(Expression.Equal(Expression.Convert(graph.Graph, typeof(object)), Expression.Constant(null)), Expression.Throw(Expression.New(typeof(ArgumentException).GetConstructor(new Type[] { typeof(string), }), Expression.Constant(graph.Graph.Name)))));
			eAs.Add(Expression.IfThen(Expression.Equal(graph.Writer, Expression.Constant(null)), Expression.Throw(Expression.New(typeof(ArgumentException).GetConstructor(new Type[] { typeof(string), }), Expression.Constant(graph.Writer.Name)))));
			eAs.Add(Expression.Assign(eie, Expression.PropertyOrField(graph.Json, @"IgnoreError")));
			eAs.Add(Expression.IfThenElse(Expression.Call(graph.Json, typeof(IJsonBuilder).GetMethod(new Func<bool>(json.HasEP).Method.Name, Type.EmptyTypes)), Expression.Block(eHs), Expression.Block(eNs)));
			eAs.Add(Expression.Label(graph.Label, graph.Writed));

			graph.Block = Expression.Block(new ParameterExpression[] { eEv, eie, }, eAs);
			graph.Lambda = Expression.Lambda(graph.Block, graph.Json, graph.Graph, eEP, graph.Stack, graph.Path, graph.Flags, graph.Writer, graph.Writed);
			graph.Handler = graph.Lambda.Compile();
			if (Utility.StaticCache.FormJsonTypeRender == null)
				Utility.StaticCache.FormJsonTypeRender = new Dictionary<Type, Delegate>();
			Utility.StaticCache.FormJsonTypeRender[type] = graph.Handler;
			return 0;
		}

		private static int RenderXmlNode(JsonBuilder json, XmlNode graph, IDictionary<object, string> stack, string path, BindingFlags bindingFlags, TextWriter writer, int writed)
		{
			if (writed == 0)
			{
				if (json.ClassName == null)
				{
					writer.Write("{ \"$:type\": \"xml\"");
					writer.Write(", \":Type\": \"" + StringUtil.JsEncode(graph.NodeType + string.Empty) + "\"");
					writer.Write(", \":Name\": \"" + StringUtil.JsEncode(graph.Name) + "\"");
					writer.Write(", \":Prefix\": \"" + StringUtil.JsEncode(graph.Prefix) + "\"");
					writer.Write(", \":LocalName\": \"" + StringUtil.JsEncode(graph.LocalName) + "\"");
					writer.Write(", \":NamespaceURI\": \"" + StringUtil.JsEncode(graph.NamespaceURI) + "\"");
				}
				else
				{
					writer.Write("{ \"$:type\": \"" + json.ClassName + "\"");
				}
			}
			switch (graph.NodeType)
			{
				case XmlNodeType.Text:
				case XmlNodeType.Attribute:
				case XmlNodeType.CDATA:
					writer.Write(", \"Value\": \"" + StringUtil.JsEncode(graph.Value) + "\"");
					break;
				case XmlNodeType.Comment:
				case XmlNodeType.DocumentType:
				case XmlNodeType.DocumentFragment:
					break;
				case XmlNodeType.Document:
				case XmlNodeType.Element:
					var v = Reflector.GetDefault(null);
					var t = string.Empty;
					if (graph.Attributes != null)
					{
						foreach (XmlAttribute xml in graph.Attributes)
						{
							if (json != null && json.TryGetEP(graph, "@" + (string.IsNullOrEmpty(xml.Prefix) ? xml.Name : (xml.Prefix + ":" + xml.Name)), ref v))
								continue;

							if (string.IsNullOrEmpty(xml.Value))
								continue;

							writer.Write(", \"@" + StringUtil.JsEncode(string.IsNullOrEmpty(xml.Prefix) ? xml.Name : (xml.Prefix + ":" + xml.Name)) + "\": \"" + StringUtil.JsEncode(xml.Value) + "\"");
						}
					}
					if (graph.HasChildNodes)
					{
						var ns = new Dictionary<string, int>();
						foreach (XmlNode xml in graph.ChildNodes)
						{
							var jn = string.IsNullOrEmpty(xml.Prefix) ? xml.Name : (xml.Prefix + ":" + xml.Name);
							if (ns.ContainsKey(jn))
							{
								ns[jn]++;
								jn = jn + "#" + ns[jn];
							}
							else
							{
								ns[jn] = 0;
							}
							if (json != null && json.TryGetEP(graph, jn, ref v))
								continue;

							switch (xml.NodeType)
							{
								case XmlNodeType.Text:
								case XmlNodeType.Attribute:
								case XmlNodeType.CDATA:
									t += xml.Value;
									break;
								case XmlNodeType.Comment:
								case XmlNodeType.DocumentType:
								case XmlNodeType.DocumentFragment:
									break;
								case XmlNodeType.Document:
								case XmlNodeType.Element:
									if (xml.NodeType == XmlNodeType.Element && (xml.Attributes == null || xml.Attributes.Count == 0))
									{
										if (xml.HasChildNodes)
										{
											v = xml;
											foreach (XmlNode xn in xml.ChildNodes)
											{
												switch (xn.NodeType)
												{
													case XmlNodeType.Text:
													case XmlNodeType.Attribute:
													case XmlNodeType.CDATA:
													case XmlNodeType.Comment:
													case XmlNodeType.DocumentType:
													case XmlNodeType.DocumentFragment:
														break;
													case XmlNodeType.Document:
													case XmlNodeType.Element:
														writer.Write(", \"" + jn + "\": ");
														writed += JsonBuilder.Render(null, json, xml, stack, path + ", " + jn, bindingFlags, writer);
														v = null;
														break;
													case XmlNodeType.EndElement:
													case XmlNodeType.EndEntity:
													case XmlNodeType.Entity:
													case XmlNodeType.EntityReference:
													case XmlNodeType.None:
													case XmlNodeType.Notation:
													case XmlNodeType.ProcessingInstruction:
													case XmlNodeType.SignificantWhitespace:
													case XmlNodeType.Whitespace:
													case XmlNodeType.XmlDeclaration:
													default:
														break;
												}
											}
											if (v != null)
												writer.Write(", \"" + jn + "\": \"" + StringUtil.JsEncode(xml.InnerText) + "\"");
										}
									}
									else
									{
										writer.Write(", \"" + jn + "\": ");
										writed += JsonBuilder.Render(null, json, xml, stack, path + ", " + jn, bindingFlags, writer);
									}
									break;
								case XmlNodeType.EndElement:
								case XmlNodeType.EndEntity:
								case XmlNodeType.Entity:
								case XmlNodeType.EntityReference:
								case XmlNodeType.None:
								case XmlNodeType.Notation:
								case XmlNodeType.ProcessingInstruction:
								case XmlNodeType.SignificantWhitespace:
								case XmlNodeType.Whitespace:
								case XmlNodeType.XmlDeclaration:
								default:
									break;
							}
						}
					}
					if (!string.IsNullOrEmpty(t))
						writer.Write(", \"Value\": \"" + StringUtil.JsEncode(t) + "\"");
					break;
				case XmlNodeType.EndElement:
				case XmlNodeType.EndEntity:
				case XmlNodeType.Entity:
				case XmlNodeType.EntityReference:
				case XmlNodeType.None:
				case XmlNodeType.Notation:
				case XmlNodeType.ProcessingInstruction:
				case XmlNodeType.SignificantWhitespace:
				case XmlNodeType.Whitespace:
				case XmlNodeType.XmlDeclaration:
				default:
					break;
			}
			writer.Write(" }");
			return writed + 1;
		}

		#region Render DataSet, DataTable, DataView, DataRow, DataRowView, IDictionary, NameObjectCollectionBase, IEnumerable

		private static int RenderDataSet(JsonBuilder json, DataSet graph, IDictionary<object, string> stack, string path, BindingFlags bindingFlags, TextWriter writer, int writed)
		{
			if (writed == 0)
				writer.Write("{ ");
			else
				writer.Write(", ");
			writer.Write("\"Name\": \"");
			writer.Write(StringUtil.JsEncode(graph.DataSetName));
			writer.Write("\", \"Tables\": [ ");
			for (var i = 0; i < graph.Tables.Count; i++)
			{
				if (i > 0)
					writer.Write(", ");
				JsonBuilder.Render(null, json, graph.Tables[i], stack, path + ", " + i, bindingFlags, writer);
			}
			writer.Write(" ] }");
			return 1;
		}

		private static int RenderDataTable(JsonBuilder json, DataTable graph, IDictionary<object, string> stack, string path, BindingFlags bindingFlags, TextWriter writer, int writed)
		{
			var cl = graph.Columns.Count;
			var cs = new List<string>();
			if (json != null && json.HasEP(graph, string.Empty))
			{
				var v = Reflector.GetDefault(null);
				for (var i = 0; i < cl; i++)
				{
					if (!json.TryGetEP(graph, graph.Columns[i].ColumnName, ref v))
						cs.Add(graph.Columns[i].ColumnName);
				}
				cl = cs.Count;
			}
			else
			{
				for (var i = 0; i < cl; i++)
					cs.Add(graph.Columns[i].ColumnName);
			}
			if (writed == 0)
				writer.Write("{ ");
			else
				writer.Write(", ");
			writer.Write("\"Name\": \"");
			writer.Write(StringUtil.JsEncode(graph.TableName));
			var ls = new List<int>();
			writer.Write("\", \"Rows\": [");
			for (var i = 0; i < graph.Rows.Count; i++)
			{
				if (i > 0)
					writer.Write(", [ ");
				else
					writer.Write(" [ ");
				for (var ii = 0; ii < cl; ii++)
				{
					if (ii > 0)
						writer.Write(", ");
					JsonBuilder.Render(null, json, graph.Rows[i][cs[ii]], stack, path + ", " + i + ", " + ii, bindingFlags, writer);
				}
				writer.Write(" ]");
			}
			writer.Write(" ], \"Columns\": [ ");
			for (var i = 0; i < cl; i++)
			{
				if (i > 0)
					writer.Write(", ");
				writer.Write('"');
				writer.Write(StringUtil.JsEncode(cs[i]));
				writer.Write('"');
			}
			writer.Write(" ]");
			writer.Write(" }");
			return 1;
		}

		private static int RenderDataView(JsonBuilder json, DataView graph, IDictionary<object, string> stack, string path, BindingFlags bindingFlags, TextWriter writer, int writed)
		{
			var cl = graph.Table.Columns.Count;
			var cs = new List<string>();
			if (json != null && json.HasEP(graph, string.Empty))
			{
				var v = Reflector.GetDefault(null);
				for (var i = 0; i < cl; i++)
				{
					if (!json.TryGetEP(graph, graph.Table.Columns[i].ColumnName, ref v))
						cs.Add(graph.Table.Columns[i].ColumnName);
				}
				cl = cs.Count;
			}
			else
			{
				for (var i = 0; i < cl; i++)
					cs.Add(graph.Table.Columns[i].ColumnName);
			}
			if (writed == 0)
				writer.Write("{ ");
			else
				writer.Write(", ");
			writer.Write("\"Name\": \"");
			writer.Write(StringUtil.JsEncode(graph.Table.TableName));
			writer.Write("\", \"RowFilter\": \"");
			writer.Write(StringUtil.JsEncode(graph.RowFilter));
			writer.Write("\", \"Sort\": \"");
			writer.Write(StringUtil.JsEncode(graph.Sort));
			writer.Write("\", \"Rows\": [");
			for (var i = 0; i < graph.Count; i++)
			{
				if (i > 0)
					writer.Write(", [ ");
				else
					writer.Write(" [ ");
				for (var ii = 0; ii < cl; ii++)
				{
					if (ii > 0)
						writer.Write(", ");
					JsonBuilder.Render(null, json, graph[i][cs[ii]], stack, path + ", " + i + ", " + ii, bindingFlags, writer);
				}
				writer.Write(" ]");
			}
			writer.Write(" ], \"Columns\": [ ");
			for (var i = 0; i < cl; i++)
			{
				if (i > 0)
					writer.Write(", ");
				writer.Write('"');
				writer.Write(StringUtil.JsEncode(cs[i]));
				writer.Write('"');
			}
			writer.Write(" ]");
			writer.Write(" }");
			return 1;
		}

		private static int RenderDataRow(JsonBuilder json, DataRow graph, IDictionary<object, string> stack, string path, BindingFlags bindingFlags, TextWriter writer, int writed)
		{
			if (writed == 0)
				writer.Write("{ ");
			else
				writer.Write(", ");
			var cs = graph.Table.Columns;
			var v = Reflector.GetDefault(null);
			for (var i = 0; i < cs.Count; i++)
			{
				if (json == null || !json.TryGetEP(graph, cs[i].ColumnName, ref v))
					v = graph[i];
				if (v == null || object.Equals(v, cs[i].DataType.GetDefault()))
					continue;

				if (i > 0)
					writer.Write(", ");
				JsonBuilder.Render("\"" + StringUtil.JsEncode(cs[i].ColumnName) + "\": ", json, v, stack, path + ", \"" + StringUtil.JsEncode(cs[i].ColumnName) + "\"", bindingFlags, writer);
			}
			writer.Write(" }");
			return 1;
		}

		private static int RenderDataRowView(JsonBuilder json, DataRowView graph, IDictionary<object, string> stack, string path, BindingFlags bindingFlags, TextWriter writer, int writed)
		{
			if (writed == 0)
				writer.Write("{ ");
			else
				writer.Write(", ");
			var cs = graph.DataView.Table.Columns;
			var v = Reflector.GetDefault(null);
			for (var i = 0; i < cs.Count; i++)
			{
				if (json == null || !json.TryGetEP(graph, cs[i].ColumnName, ref v))
					v = graph.Row[i];
				if (v == null || object.Equals(v, cs[i].DataType.GetDefault()))
					continue;

				if (i > 0)
					writer.Write(", ");
				JsonBuilder.Render("\"" + StringUtil.JsEncode(cs[i].ColumnName) + "\": ", json, v, stack, path + ", \"" + StringUtil.JsEncode(cs[i].ColumnName) + "\"", bindingFlags, writer);
			}
			writer.Write(" }");
			return 1;
		}

		private static int RenderDataReader(JsonBuilder json, IDataReader graph, IDictionary<object, string> stack, string path, BindingFlags bindingFlags, TextWriter writer, int writed)
		{
			var result = 0;
			if (writed == 0)
				writer.Write("{ ");
			else
				writer.Write(", ");
			writer.Write("\"Results\": [");
			do
			{
				var cl = graph.FieldCount;
				var cs = new List<string>();
				if (json != null && json.HasEP(graph, string.Empty))
				{
					var v = Reflector.GetDefault(null);
					for (var i = 0; i < cl; i++)
					{
						if (!json.TryGetEP(graph, graph.GetName(i), ref v))
							cs.Add(graph.GetName(i));
					}
					cl = cs.Count;
				}
				else
				{
					for (var i = 0; i < cl; i++)
						cs.Add(graph.GetName(i));
				}
				if (result > 0)
					writer.Write(", ");
				writer.Write("{ \"Rows\": [");
				for (var row = 0; graph.Read(); row++)
				{
					if (row > 0)
						writer.Write(", [ ");
					else
						writer.Write(" [ ");
					for (var col = 0; col < cl; col++)
					{
						if (col > 0)
							writer.Write(", ");
						JsonBuilder.Render(null, json, graph[col], stack, path + ", " + row + ", " + col, bindingFlags, writer);
					}
					writer.Write(" ]");
				}
				writer.Write(" ], \"Fields\": [ ");
				for (var i = 0; i < cl; i++)
				{
					if (i > 0)
						writer.Write(", ");
					writer.Write('"');
					writer.Write(StringUtil.JsEncode(cs[i]));
					writer.Write('"');
				}
				writer.Write(" ]");
				writer.Write(" }");
				result++;
			} while (graph.NextResult());
			writer.Write(" ]");
			writer.Write(" }");
			return 1;
		}

		private static int RenderDictionary(JsonBuilder json, IDictionary graph, IDictionary<object, string> stack, string path, BindingFlags bindingFlags, TextWriter writer, int writed)
		{
			if (writed == 0)
				writer.Write("{ ");
			else
				writer.Write(", ");
			var i = 0;
			var v = Reflector.GetDefault(null);
			foreach (var key in graph.Keys)
			{
				var k = key + string.Empty;
				if (json == null || !json.TryGetEP(graph, k, ref v))
					v = graph[key];
				if (v == null)
					continue;

				if (i > 0)
					writer.Write(", ");
				i = JsonBuilder.Render("\"" + StringUtil.JsEncode(k) + "\": ", json, v, stack, path + ", \"" + StringUtil.JsEncode(k) + "\"", bindingFlags, writer);
			}
			writer.Write(" }");
			return 1;
		}

		private static int RenderNameObjectCollection(JsonBuilder json, NameObjectCollectionBase graph, IDictionary<object, string> stack, string path, BindingFlags bindingFlags, TextWriter writer, int writed)
		{
			if (writed == 0)
				writer.Write("{ ");
			else
				writer.Write(", ");
			var i = 0;
			var v = Reflector.GetDefault(null);
			foreach (string key in graph.Keys)
			{
				if (json == null || !json.TryGetEP(graph, key, ref v))
					v = NameObjectCollection.Get(graph, key);
				if (v == null)
					continue;

				if (i > 0)
					writer.Write(", ");
				i = JsonBuilder.Render("\"" + StringUtil.JsEncode(key) + "\": ", json, v, stack, path + ", \"" + StringUtil.JsEncode(key) + "\"", bindingFlags, writer);
			}
			writer.Write(" }");
			return 1;
		}

		private static int RenderEnumerable(JsonBuilder json, IEnumerable graph, IDictionary<object, string> stack, string path, BindingFlags bindingFlags, TextWriter writer, int writed)
		{
			if (writed == 0)
			{
				writer.Write("[ ");
			}
			else
			{
				writer.Write(", \"Items\": [ ");
				path += ", \"Items\"";
			}
			var i = 0;
			foreach (var o in graph)
			{
				if (i > 0)
					writer.Write(", ");
				JsonBuilder.Render(null, json, o, stack, path + ", " + i, bindingFlags, writer);
				i++;
			}
			if (writed == 0)
				writer.Write(" ]");
			else
				writer.Write(" ] }");
			return i;
		}

		#endregion

		private static int RenderSerializable(JsonBuilder json, object graph, IDictionary<object, string> stack, string path, BindingFlags bindingFlags, TextWriter writer, int writed, IJsonSerializable serializable)
		{
			if (serializable == null)
				return 0;

			var members = serializable.GetMembers(json, path, bindingFlags);
			if (members == null || members.Length == 0)
				return 0;

			var i = writed;
			var v = Reflector.GetDefault(null);
			foreach (var m in members)
			{
				if (json == null || !json.TryGetEP(graph, m.Name, ref v))
				{
					var p = m as PropertyInfo;
					if (p != null)
					{
						if (p.GetGetMethod() == null || p.GetIndexParameters().Length > 0)
						{
							v = null;
						}
						else
						{
							v = p.GetValue(graph, null);
							if (v == null || object.Equals(v, p.PropertyType.GetDefault()))
								v = null;
						}
					}
					else
					{
						var f = m as FieldInfo;
						if (f != null)
						{
							v = f.GetValue(graph);
							if (v == null || object.Equals(v, f.FieldType.GetDefault()))
								v = null;
						}
					}
				}
				if (v == null)
					continue;

				if (i > 0)
					writer.Write(", ");
				i += JsonBuilder.Render("\"" + StringUtil.JsEncode(m.Name) + "\": ", json, v, stack, path + ", \"" + StringUtil.JsEncode(m.Name) + "\"", bindingFlags, writer);
			}
			return i - writed;
		}

		private static int RenderProperties(JsonBuilder json, object graph, IDictionary<object, string> stack, string path, BindingFlags bindingFlags, TextWriter writer, int writed, PropertyInfo[] properties)
		{
			if (properties == null || properties.Length == 0)
				return 0;

			foreach (var m in properties)
			{
				var v = Reflector<object>.DefaultValue;
				if (!JsonBuilder._MemberExcludeCache.Contains(m))//.ContainsKey(m))
				{
					if (m.GetIndexParameters().Length > 0)
						JsonBuilder._MemberExcludeCache[m] = m;
					else if (m.GetGetMethod() == null)
						JsonBuilder._MemberExcludeCache[m] = m;
					else if (m.GetCustomAttributes(typeof(JsonAttribute), true).Length > 0)//JsonAttribute，不可序列化。
						JsonBuilder._MemberExcludeCache[m] = m;
					else if (m.GetCustomAttributes(typeof(XmlIgnoreAttribute), true).Length > 0)//XmlIgnoreAttribute，不可序列化。
						JsonBuilder._MemberExcludeCache[m] = m;
					else if (m.GetCustomAttributes(typeof(AssociationAttribute), true).Length > 0)//AssociationAttribute，不可序列化。
						JsonBuilder._MemberExcludeCache[m] = m;
					else
						JsonBuilder._MemberExcludeCache[m] = null;
				}
				if (json != null && json.TryGetEP(graph, m.Name, ref v))//使用全局扩展覆盖其它明确定义的扩展。
				{
					if (v != null)
					{
						if (writed > 0)
							writer.Write(", ");
						writed += JsonBuilder.Render("\"" + StringUtil.JsEncode(m.Name) + "\": ", json, v, stack, path + ", \"" + StringUtil.JsEncode(m.Name) + "\"", bindingFlags, writer);//使用全局扩展覆盖其它明确定义的扩展。
					}
					continue;
				}

				if (JsonBuilder._MemberExcludeCache[m] != null)
					continue;

				if (json == null || json.IgnoreError)
				{
					try
					{
						v = m.GetValue(graph, null);
					}
					catch (Exception x)
					{
						x.SetLastError();
						v = x.ToString();
					}
				}
				else
				{
					v = m.GetValue(graph, null);
				}
				if (v == null || object.Equals(v, m.PropertyType.GetDefault()))
					continue;

				if (writed > 0)
					writer.Write(", ");
				writed += JsonBuilder.Render("\"" + StringUtil.JsEncode(m.Name) + "\": ", json, v, stack, path + ", \"" + StringUtil.JsEncode(m.Name) + "\"", bindingFlags, writer);
			}
			return writed;
		}

		private static int RenderFields(JsonBuilder json, object graph, IDictionary<object, string> stack, string path, BindingFlags bindingFlags, TextWriter writer, int writed, FieldInfo[] fields)
		{
			if (fields == null || fields.Length == 0)
				return 0;

			foreach (var m in fields)
			{
				var v = Reflector<object>.DefaultValue;
				if (!JsonBuilder._MemberExcludeCache.Contains(m))//.ContainsKey(m))
				{
					if (m.GetCustomAttributes(typeof(AssociationAttribute), true).Length > 0)
						JsonBuilder._MemberExcludeCache[m] = m;
					else if (m.GetCustomAttributes(typeof(JsonAttribute), true).Length > 0)//JsonAttribute，不可序列化。
						JsonBuilder._MemberExcludeCache[m] = m;
					else if (m.GetCustomAttributes(typeof(XmlIgnoreAttribute), true).Length > 0)//XmlIgnoreAttribute，不可序列化。
						JsonBuilder._MemberExcludeCache[m] = m;
					else if (m.GetCustomAttributes(typeof(AssociationAttribute), true).Length > 0)//AssociationAttribute，不可序列化。
						JsonBuilder._MemberExcludeCache[m] = m;
					else
						JsonBuilder._MemberExcludeCache[m] = null;
				}
				if (json != null && json.TryGetEP(graph, m.Name, ref v))//使用全局扩展覆盖其它明确定义的扩展。
				{
					if (v != null)
					{
						if (writed > 0)
							writer.Write(", ");
						writed += JsonBuilder.Render("\"" + StringUtil.JsEncode(m.Name) + "\": ", json, v, stack, path + ", \"" + StringUtil.JsEncode(m.Name) + "\"", bindingFlags, writer);//使用全局扩展覆盖其它明确定义的扩展。
					}
					continue;
				}

				if (JsonBuilder._MemberExcludeCache[m] != null)
					continue;

				v = m.GetValue(graph);
				if (v == null || object.Equals(v, m.FieldType.GetDefault()))
					continue;

				if (writed > 0)
					writer.Write(", ");
				writed += JsonBuilder.Render("\"" + StringUtil.JsEncode(m.Name) + "\": ", json, v, stack, path + ", \"" + StringUtil.JsEncode(m.Name) + "\"", bindingFlags, writer);
			}
			return writed;
		}

		/// <summary>
		/// 设置变量名
		/// </summary>
		/// <param name="parent">父变量名，如果为“/”则为“window”对象</param>
		/// <param name="variable">变量名</param>
		/// <returns>变量名</returns>
		public string SetVariable(string parent, string variable)
		{
			if (string.IsNullOrEmpty(variable))
				return variable;

			if (string.IsNullOrEmpty(parent))
				this.Variable = variable;
			else if (parent == "/" || parent == "\\" || parent == "~")
				this.Variable = "window[\"" + variable + "\"]";
			else
				this.Variable = parent + "[\"" + variable + "\"]";
			return this.Variable;
		}
		/// <summary>
		/// 设置变量名
		/// </summary>
		/// <param name="parent">父变量名，如果为“/”则为“window”对象</param>
		/// <param name="var0">变量名，如果为空，则为“var1”的值</param>
		/// <param name="var1">变量名</param>
		/// <returns>变量名</returns>
		public string SetVariable(string parent, string var0, string var1)
		{
			return this.SetVariable(parent, var0 ?? var1);
		}
		/// <summary>
		/// 设置变量名
		/// </summary>
		/// <param name="parent">父变量名，如果为“/”则为“window”对象</param>
		/// <param name="var0">变量名，如果为空，则为“var1”的值</param>
		/// <param name="var1">变量名，如果为空，则为“var2”的值</param>
		/// <param name="var2">变量名</param>
		/// <returns>变量名</returns>
		public string SetVariable(string parent, string var0, string var1, string var2)
		{
			return this.SetVariable(parent, (var0 ?? var1) ?? var2);
		}

		/// <summary/>
		public static JsonBuilder Create(object graph = null)
		{
			return new JsonBuilder(graph ?? JsonBuilder.Any, string.Empty);
		}

		/// <summary>
		/// 序列化成Json字符串
		/// </summary>
		/// <returns>用Json表示对象的字符串</returns>
		public override string ToString()
		{
			if (this._Graph is JsonGraph)
				return this._Graph.ToString();

			var sw = new StringWriter();
			JsonBuilder.Render(null, this, this._Graph, null, null, BindingFlags.Public | BindingFlags.Instance, sw);
			return sw.ToString();
		}
		/// <summary>
		/// 序列化成Json字符串
		/// </summary>
		/// <param name="staticMember">是否成生静态成员对象</param>
		/// <returns>用Json表示对象的字符串</returns>
		public string ToString(bool staticMember)
		{
			if (this._Graph is JsonGraph)
				return this._Graph.ToString();

			var sw = new StringWriter();
			if (staticMember)
				JsonBuilder.Render(null, this, this._Graph, null, null, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.FlattenHierarchy, sw);
			else
				JsonBuilder.Render(null, this, this._Graph, null, null, BindingFlags.Public | BindingFlags.Instance, sw);
			return sw.ToString();
		}
		/// <summary>
		/// 序列化成Json字符串
		/// </summary>
		/// <param name="bindingFlags">指示序列化成员的标志</param>
		/// <returns>用Json表示对象的字符串</returns>
		public string ToString(BindingFlags bindingFlags)
		{
			if (this._Graph is JsonGraph)
				return this._Graph.ToString();

			var sw = new StringWriter();
			JsonBuilder.Render(null, this, this._Graph, null, null, bindingFlags, sw);
			return sw.ToString();
		}

		/// <summary>
		/// 序列化成Json字符串
		/// </summary>
		/// <param name="graph">要转换的对象</param>
		/// <returns>用Json表示对象的字符串</returns>
		public static string ToString(object graph)
		{
			if (graph is JsonGraph)
				return graph.ToString();

			var sw = new StringWriter();
			JsonBuilder.Render(null, new JsonBuilder(graph, string.Empty), graph, null, null, BindingFlags.Public | BindingFlags.Instance, sw);
			return sw.ToString();
		}
		/// <summary>
		/// 序列化成Json字符串
		/// </summary>
		/// <param name="graph">要转换的对象</param>
		/// <param name="staticMember">是否成生静态成员对象</param>
		/// <returns>用Json表示对象的字符串</returns>
		public static string ToString(object graph, bool staticMember)
		{
			if (graph is JsonGraph)
				return graph.ToString();

			var sw = new StringWriter();
			if (staticMember)
				JsonBuilder.Render(null, new JsonBuilder(graph, string.Empty), graph, null, null, BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | BindingFlags.FlattenHierarchy, sw);
			else
				JsonBuilder.Render(null, new JsonBuilder(graph, string.Empty), graph, null, null, BindingFlags.Public | BindingFlags.Instance, sw);
			return sw.ToString();
		}
		/// <summary>
		/// 序列化成Json字符串
		/// </summary>
		/// <param name="graph">要转换的对象</param>
		/// <param name="bindingFlags">指示序列化成员的标志</param>
		/// <returns>用Json表示对象的字符串</returns>
		public static string ToString(object graph, BindingFlags bindingFlags)
		{
			if (graph is JsonGraph)
				return graph.ToString();

			var sw = new StringWriter();
			JsonBuilder.Render(null, new JsonBuilder(graph, string.Empty), graph, null, null, bindingFlags, sw);
			return sw.ToString();
		}

		/// <summary>
		/// 尝试获取扩展属性
		/// </summary>
		/// <param name="extend">扩展集</param>
		/// <param name="key">要尝试获取属性的对象，如果是【Empty】则表示全局扩展</param>
		/// <param name="name">要尝试获取的属性名称</param>
		/// <param name="value">要尝试获取的属性值</param>
		/// <returns>是否获取成功</returns>
		public static bool TryGetEP(IDictionary<object, IDictionary<string, object>> extend, object key, string name, ref object value)
		{
			var v = false;
			if (extend == null)
				return v;

			var vs = Reflector<string, object>.NullDictionaryI;
			if (key != null)//先查指定对象扩展
			{
				if (extend.TryGetValue(key, out vs))//如果指定对象扩展存在
				{
					if (name == null)//如果名称为空表示仅判断指定扩展是否存在，返回：True = 存在
						return true;

					v = vs.TryGetValue(name, out value);//查找扩展
					if (v)//如果扩展存在，返回：True = 存在
						return v;

					if (name != string.Empty)//如果查找指定扩展，则查排除扩展
					{
						v = vs.TryGetValue(string.Empty, out value);
						if (v)//如果排除扩展存在
						{
							var i = StringUtil.ContainsInclude(value, name);
							if (i > 0)//大于零表示包含，返回未找到值
							{
								value = null;
								return false;
							}

							if (i < 0)//大于零表示排除，返回已找到空
							{
								value = Reflector.Struct<EmptyJson>.Nullable;//返回：可空对象
								return true;//返回：True = 存在
							}
						}
					}//if (name != string.Empty)//如果查找指定扩展，则查排除扩展
				}//if (this._EP.TryGetValue(key, out vs))//如果指定对象扩展存在
			}//if (key != null)//先查指定对象扩展

			key = JsonBuilder.Empty;
			if (extend.TryGetValue(key, out vs))//如果指定对象扩展存在
			{
				if (name == null)//如果名称为空表示仅判断指定扩展是否存在，返回：True = 存在
					return true;

				v = vs.TryGetValue(name, out value);//查找扩展
				if (v)//如果扩展存在，返回：True = 存在
					return v;

				if (name != string.Empty)//如果查找指定扩展，则查排除扩展
				{
					v = vs.TryGetValue(string.Empty, out value);
					if (v)//如果排除扩展存在
					{
						var i = StringUtil.ContainsInclude(value, name);
						if (i > 0)//大于零表示包含，返回未找到值
						{
							value = null;
							return false;
						}

						if (i < 0)//大于零表示排除，返回已找到空
						{
							value = Reflector.Struct<EmptyJson>.Nullable;//返回：可空对象
							return true;//返回：True = 存在
						}
					}
				}//if (name != string.Empty)//如果查找指定扩展，则查排除扩展
			}//if (this._EP.TryGetValue(key, out vs))//如果指定对象扩展存在

			return false;
		}
	}

	/// <summary>
	/// 直接输出内容的 Json 对象类型
	/// </summary>
	public class JsonGraph : IJsonBuilder, IScriptCode
	{
		bool IJsonBuilder.TryGetEP(string name, ref object value)
		{
			return false;
		}

		bool IJsonBuilder.TryGetEP(object key, string name, ref object value)
		{
			return false;
		}

		object IJsonBuilder.GetEP(string name)
		{
			return null;
		}

		object IJsonBuilder.SetEP(string name, object value)
		{
			throw new NotImplementedException();
		}

		object IJsonBuilder.GetEP(object key, string name)
		{
			return null;
		}

		object IJsonBuilder.SetEP(object key, string name, object value)
		{
			throw new NotImplementedException();
		}

		object IJsonBuilder.AppendEP(string name, object value)
		{
			throw new NotImplementedException();
		}

		object IJsonBuilder.AppendEP(object key, string name, object value)
		{
			throw new NotImplementedException();
		}

		string IJsonBuilder.ClassName
		{
			get
			{
				return null;
			}
			set
			{
				throw new NotSupportedException();
			}
		}

		string IJsonBuilder.Variable
		{
			get
			{
				return null;
			}
			set
			{
				throw new NotSupportedException();
			}
		}

		/// <summary/>
		public object Graph { get; set; }

		bool IJsonBuilder.IgnoreError
		{
			get
			{
				return false;
			}
			set
			{
				throw new NotSupportedException();
			}
		}

		void IJsonBuilder.RemoveEP(object key)
		{
			throw new NotSupportedException();
		}

		void IJsonBuilder.RemoveEP(object key, string name)
		{
			throw new NotSupportedException();
		}

		void IJsonBuilder.RemoveEP()
		{
			throw new NotSupportedException();
		}

		bool IJsonBuilder.HasEP()
		{
			return false;
		}

		bool IJsonBuilder.HasEP(string name)
		{
			return false;
		}

		bool IJsonBuilder.HasEP(object key, string name)
		{
			return false;
		}

		object IJsonBuilder.this[string name]
		{
			get
			{
				return null;
			}
			set
			{
				throw new NotSupportedException();
			}
		}

		object IJsonBuilder.this[object key, string name]
		{
			get
			{
				return null;
			}
			set
			{
				throw new NotSupportedException();
			}
		}

		/// <summary/>
		public int Render(TextWriter output)
		{
			return this.Render(output, this.Graph, null, null, BindingFlags.Default, null);
		}

		/// <summary>
		/// 输入指定对象的Json字符流
		/// </summary>
		/// <param name="output">Json书写器</param>
		/// <param name="graph">要输出的对象</param>
		/// <param name="stack">防止序列化死递归的堆对象</param>
		/// <param name="path">防止序列化死递归的引用路径</param>
		/// <param name="flags">指示序列化成员的标志</param>
		/// <param name="prefix">前缀字符串</param>
		/// <returns>是否已输出，为零表示没有任何输出，需要生成器继续处理。</returns>
		public int Render(TextWriter output, object graph, IDictionary<object, string> stack, string path, BindingFlags flags, string prefix)
		{
			if (graph == null)
			{
				output.Write(JsonBuilder.NullString);
				return 1;
			}

			//var c = graph as Control;
			//if (c != null)
			//{
			//    var htw = new HtmlTextWriter(output);
			//    c.RenderControl(htw);
			//    return 1;
			//}

			var t = graph as string;
			if (t != null)
			{
				output.Write(t);
				return 1;
			}

			output.Write(graph);
			return 1;
		}

		string IJsonBuilder.SetVariable(string parent, string variable)
		{
			throw new NotSupportedException();
		}

		string IJsonBuilder.SetVariable(string parent, string var0, string var1)
		{
			throw new NotSupportedException();
		}

		string IJsonBuilder.SetVariable(string parent, string var0, string var1, string var2)
		{
			throw new NotSupportedException();
		}

		string IJsonBuilder.ToString(BindingFlags bindingFlags)
		{
			if (this.Graph == null)
				return null;

			var t = this.Graph as string;
			if (t != null)
				return t;

			return this.Graph.ToString();
		}

		string IJsonBuilder.ToString(bool staticMember)
		{
			if (this.Graph == null)
				return null;

			var t = this.Graph as string;
			if (t != null)
				return t;

			return this.Graph.ToString();
		}

		/// <summary/>
		public override string ToString()
		{
			if (this.Graph == null)
				return null;

			var t = this.Graph as string;
			if (t != null)
				return t;

			return this.Graph.ToString();
		}

		string IScriptCode.ToString(string language)
		{
			if (this.Graph == null)
				return null;

			var t = this.Graph as string;
			if (t != null)
				return t;

			return this.Graph.ToString();
		}
	}

	/// <summary>
	/// 如果此值附加在属性上，表示不可序列化此属性，如果此值附加到类型上，则表示可直接序列化些类型。
	/// </summary>
	[Serializable]
	[ComVisible(true)]
	[ClassInterface(ClassInterfaceType.None)]
	[AttributeUsage(AttributeTargets.All, Inherited = true, AllowMultiple = true)]
	public class JsonAttribute : Attribute
	{
	}
}
